package com.app.serial.jsso;

import com.app.serial.utils.HexByteUtil;
import com.google.common.collect.Maps;
import jssc.SerialPort;
import jssc.SerialPortEventListener;
import jssc.SerialPortException;
import jssc.SerialPortList;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


/**
 * @author Administrator
 * jsc串口工具类  支持多串口模式
 */
@Slf4j
@Component
public class JsscComDriver {

    public static Map<String, SerialPort> serialPortMap= new ConcurrentHashMap();

    /**
     * 串口启动器
     *
     * @param portName 串口号
     * @param baudRate 波特率
     * @param classZZ   串口监听类
     */
    public synchronized static void openSerialPort(String portName, int baudRate ,Class<?> classZZ) {
        SerialPort serialPort = new SerialPort(portName);
        if (!serialPort.isOpened()) {
            try {
                //打开指定串口
                serialPort.openPort();
                //设置（ 比特率、数据位、停止位、奇偶校验位）
                serialPort.setParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
                //准备监听事件
                int mask = SerialPort.MASK_RXCHAR + SerialPort.MASK_CTS + SerialPort.MASK_DSR;
                //设置事件监听任务
                serialPort.setEventsMask(mask);
                //增加串口事件监听器
                SerialPortEventListener instance =(SerialPortEventListener) classZZ.getConstructor(SerialPort.class).newInstance(serialPort);
                serialPort.addEventListener(instance);
                serialPortMap.put(portName,serialPort);
            } catch (SerialPortException ex) {
                switch (ex.getExceptionType()) {
                    case SerialPortException.TYPE_PORT_BUSY:
                        log.info("串口[{}]被占用", portName);
                        break;
                    case SerialPortException.TYPE_PORT_NOT_FOUND:
                        log.info("未发现对应串口:{}", portName);
                        break;
                    default:
                        log.info("串口打开失败:{}", ex.getMessage());
                }
            } catch (Exception e) {
                log.info("创建串口监听器失败:{}", e);
            }
        }
        log.info("串口[{}]状态为:{}", portName, serialPort.isOpened());
    }

    /**
     * 往对应串口发送消息
     * @param portName
     * @param command  指令
     */
    public synchronized static void sendMessage(String portName, String command){
        log.info("发送到串口[{}]消息为:{}", portName, command);
        if (serialPortMap.containsKey(portName)){
            SerialPort serialPort = serialPortMap.get(portName);
            if (serialPort.isOpened()){
                try {
                    byte[] msgBuffer = HexByteUtil.hexToByteArray(command);
                    serialPort.writeBytes(msgBuffer);
                } catch (SerialPortException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 搜索串口列表
     * @return
     */
    public synchronized static HashMap<String, Object> getPortList(){
        HashMap<String, Object> map = Maps.newHashMap();
        String[] portNames = SerialPortList.getPortNames();
        log.info("设备串口列表为:{}", Arrays.asList(portNames));
        map.put("port",portNames);
        return map;
    }

    public static void main(String[] args) {
        JsscComDriver.openSerialPort("COM8", 115200, SerialPortListener.class);
    }
}

